fn twice(x: i32, f: &dyn Fn(i32) -> i32) -> i32 {
    f(f(x))
}

fn twice2<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
    f(f(x))
}

fn my_map<T>(vs: &[i32], f: T) -> Vec<i32>
where
    T: FnMut(&i32) -> i32,
{
    vs.iter().map(f).collect()
}

fn my_inc(i: i32) -> i32 {
    i + 1
}

#[test]
fn basic_closure_test() {
    let add_one = |x| x + 1;
    let ret = twice(1, &add_one);
    assert_eq!(3, ret);
    let ret = twice(1, &my_inc);
    assert_eq!(3, ret);

    let ret = twice2(1, add_one);
    assert_eq!(3, ret);
    let ret = twice2(1, my_inc);
    assert_eq!(3, ret);

    assert_eq!(2, add_one(1));
    assert_eq!(2, my_inc(1));

    let lst = vec![1, 2, 3, 4];
    let ret = my_map(&lst, |x| x * x);
    println!("ret =  {:?}", ret);
}
